package com.example.spidertp.core.service.impl;

import com.example.spidertp.core.SpiderThreadPool;
import com.example.spidertp.core.SpiderThreadPoolFactory;
import com.example.spidertp.core.model.enums.TpLifecycleTypeEnum;
import com.example.spidertp.core.model.param.SpiderThreadPoolArgsParam;
import com.example.spidertp.core.model.vo.SpiderThreadPoolArgsVo;
import com.example.spidertp.core.model.vo.SpiderThreadPoolLivingStateVo;
import com.example.spidertp.core.service.ArgumentService;
import com.example.spidertp.core.service.TpArgumentRecordService;
import com.example.spidertp.core.service.TpLifecycleService;
import com.example.spidertp.exception.BusinessException;
import com.example.spidertp.handler.SpiderRejectedPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author xiong.bo
 * @version 1.0
 * @date 2022/9/17 4:05 下午
 */

@Service
public class ArgumentServiceImpl implements ArgumentService {

    @Autowired
    private TpLifecycleService tpLifecycleService;
    @Autowired
    private TpArgumentRecordService tpArgumentRecordService;

    @Override
    public SpiderThreadPoolArgsVo getTreadPollArgs(String poolName) {
        SpiderThreadPool threadPool = SpiderThreadPoolFactory.getThreadPool(poolName);
        if (null == threadPool) {
            throw new BusinessException("线程池[" + poolName + "]不存在");
        }
        SpiderThreadPoolArgsVo result = new SpiderThreadPoolArgsVo();
        result.setCorePoolSize(threadPool.getCorePoolSize());
        result.setMaximumPoolSize(threadPool.getMaximumPoolSize());
        result.setKeepAliveTime(threadPool.getKeepAliveTime(TimeUnit.SECONDS));
        result.setUnit(TimeUnit.SECONDS);
        result.setWorkQueue(threadPool.getQueue());
        return result;
    }

    @Override
    public SpiderThreadPoolArgsVo adjustPollArgs(SpiderThreadPoolArgsParam param) {
        String poolName = param.getPoolName();
        SpiderThreadPool threadPool = SpiderThreadPoolFactory.getThreadPool(poolName);
        if (null == threadPool) {
            throw new BusinessException("线程池[" + poolName + "]不存在");
        }
        //记录线程池核心参数变更记录
        tpArgumentRecordService.createRecord(param.getPoolName(), threadPool, param);

        if (!ObjectUtils.isEmpty(param.getCorePoolSize())) {
            threadPool.setCorePoolSize(param.getCorePoolSize());
        }
        if (!ObjectUtils.isEmpty(param.getMaximumPoolSize())) {
            threadPool.setMaximumPoolSize(param.getMaximumPoolSize());
        }
        if (!ObjectUtils.isEmpty(param.getKeepAliveTime())) {
            threadPool.setKeepAliveTime(param.getKeepAliveTime(), TimeUnit.SECONDS);
        }

        if (!ObjectUtils.isEmpty(param.getRejectedHandler())) {
            switch (param.getRejectedHandler()) {
                case "AbortPolicy":
                    threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
                    break;
                case "DiscardPolicy":
                    threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
                    break;
                case "DiscardOldestPolicy":
                    threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
                    break;
                case "CallerRunsPolicy":
                    threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
                    break;
                case "SpiderRejectedPolicy":
                    threadPool.setRejectedExecutionHandler(new SpiderRejectedPolicy());
                    break;
                default:
            }
        }
        //记录线程池调参
        tpLifecycleService.createTpRecord(param.getPoolName(), threadPool, TpLifecycleTypeEnum.ADJUST);

        return getTreadPollArgs(param.getPoolName());
    }

    @Override
    public SpiderThreadPoolLivingStateVo getTreadPollLivingState(String poolName) {
        SpiderThreadPool threadPool = SpiderThreadPoolFactory.getThreadPool(poolName);
        if (null == threadPool) {
            throw new BusinessException("线程池[" + poolName + "]不存在");
        }
        SpiderThreadPoolLivingStateVo result = new SpiderThreadPoolLivingStateVo();
        result.setCorePoolSize(threadPool.getCorePoolSize());
        result.setMaximumPoolSize(threadPool.getMaximumPoolSize());
        result.setKeepAliveTime(threadPool.getKeepAliveTime(TimeUnit.SECONDS));
        result.setUnit(TimeUnit.SECONDS);
        result.setWorkQueueSize(threadPool.getQueue().size());
        result.setQueueCapacity(threadPool.getQueueCapacity());

        result.setPoolSize(threadPool.getPoolSize());
        result.setActiveCount(threadPool.getActiveCount());
        result.setCompletedTaskCount(threadPool.getCompletedTaskCount());
        result.setLargestPoolSize(threadPool.getLargestPoolSize());
        result.setTaskCount(threadPool.getTaskCount());
        return result;
    }
}
